Problem statement: In this project, we tried to make classifications of the trails based on their length and change in elevation. We also made one function that would simplify the process of classification. To generate this analysis, we used boundary, buildings, contours_3m, and trails layers from macleish package and contours250k layer from MassGIS.
#devtools::install_github("beanumber/macleish")
library(tidyverse)
library(sf)
library(macleish)
library(leaflet)
library(dplyr)
library(lwgeom)
library(ggplot2)
#read contours250k file
elevation <- st_read("contours250k/CONTOURS250K_ARC.shp")
#plot the elevation data
plot(st_geometry(elevation))
We first plotted the elevation map of Massachusetts illustrating the number of feet or meters the state rises above sea level.
#intersect the elevation data and the macleish_layers[["boundary"]] to get the elevation data for the macleish area
elevation <- st_transform(elevation, 4326)
elevInter <-
elevation %>%
st_intersection(macleish_layers[["boundary"]])
#plot the elevation layer and the macleish trails layer together in the ggplot
ggplot() +
geom_sf(data = elevInter, aes(color = factor(CONTOUR_FT), colors = "Set1")) +
geom_sf(data = macleish_layers[["trails"]], aes(color = factor(name), alpha = 0.8, lwd = 1.2)) +
theme(legend.text=element_text(size=15))
To rate the difficulty of the trail, we wanted to check the change of elevation. We made a contour map of the MacLeish Field Station, using different colors of lines to represent different contours and plotted the trails on the contour map. In this graph, each intersection of contour lines and trails represents a 30 ft change in elevation of that trail. To see intersections more clearly, we changed the alpha and the size of the lines so that pathways can stand out from the contour lines. We created a leaflet map to make an interactive visualization of elevation and trails as follows.
#plot the elevation data and the trails in an open street map in leaflet
leaflet() %>%
addTiles() %>%
addPolylines(data = st_geometry(elevInter), weight = 2) %>%
addPolylines(data = st_geometry(macleish_layers[["trails"]]), color = macleish_layers[["trails"]]$color) %>%
addProviderTiles(providers$OpenStreetMap)
#change the color name in macleish trails
newTrails <- macleish_layers[["trails"]] %>%
mutate(colorName = tolower(color))
#calculate each part of the length of the trail
length <-
macleish_layers[["trails"]] %>%
group_by(name) %>%
st_length()
#make a new column in newTrails data frame
newTrails <-
newTrails %>%
mutate(length = 1)
#change the value in the length column to the corresponding value in length set
for (k in 1:nrow(newTrails)){
newTrails$length[k] <- length[k]
}
#get the total length of each trail
newTrails <-
newTrails %>%
group_by(name) %>%
summarise(length = sum(length)) %>%
arrange(desc(length))
#intersect elevation with trails to get the change of trails in the contour line
trailInter <-
elevation %>%
st_intersection(macleish_layers[["trails"]])
#the trails with NA has a change in elevation of 0
trailInter <-
trailInter %>%
group_by(name) %>%
summarise(ele = ifelse(n_distinct(CONTOUR_FT) != 1, sd(CONTOUR_FT), 0)) %>%
arrange(desc(ele))
We wanted to look at the exact number of the length and the change in elevation to get a more accurate rating. Therefore, we generated the table newTrails to calculate the total length of each path and the table trailInter to calculate the change in elevation. For the elevation change, we computed the standard deviation of value of the contour intersection between the elevation data and the macleish trail data for each trail. Higher standard deviation represents more changes in elevation and higher level of difficulty, while lower standard deviation represents less changes in elevation and lower level of difficulty. If a trail doesn’t show up in the trailInter table, we would regard it as there is no intersection between the contour lines and that trail which means there is barely any change in elevation.
#build the joined data frame with the level
joinTrail <-
macleish_layers[["trails"]] %>%
st_join(trailInter, join = st_crosses)
## although coordinates are longitude/latitude, st_crosses assumes that they are planar
newTrailsNone <-
st_set_geometry(newTrails, NULL)
trailInterNone <-
st_set_geometry(trailInter, NULL)
joined <-
newTrailsNone %>%
left_join(trailInterNone, by = "name")
joined$ele[is.na(joined$ele)] <- 0
joined <-
joined %>%
mutate(difficulty = 0.4 * as.numeric(length) + 0.6 * as.numeric(ele)) %>%
arrange(desc(difficulty))
joined$ID <- seq.int(nrow(joined))
joined <-
joined %>%
mutate(level = ifelse(ID < 4, "hard", ifelse(ID > 6, "easy", "moderate")))
joined
#add the different levels to the macleish trails
macleish_layers[["trails"]] <-
macleish_layers[["trails"]] %>%
inner_join(joined, by = "name")
We then joined newTrails and trailInter together, caluculating the difficulty following the formula \(diffculty = 0.4 \cdot length+ 0.6\cdot ele\) Considering it’s more diffcult to ride uphills than the flat, we assigned 0.4 for length and 0.6 for the standard deviation of elevation. We ranked the difficulty, for the three trails with the highest degrees of difficulty, which are Snowmobile Trail, Eastern Loop, and Western Loop, we rated them as in the level of “Difficult.” For the three trails with the lowest level of difficulty, which are entry trail, Driveway, Easy Out, we classified them in the level of “Easy.” And the rest of three trails, which are Poplar Hill Road, Porcupine Trail, and Vernal Pool Loop, we rated them in the level of “Moderate.”
#set color palette
pall <- colorNumeric(palette="viridis",
domain= elevInter$CONTOUR_FT)
palTrail <- colorFactor(c("red", "blue", "black"), domain = macleish_layers[["trails"]]$level)
#plot contour line and trails with leaflet
leaflet(data=macleish_layers[["trails"]]) %>%
addTiles() %>%
addPolylines(data=elevInter,
color = ~pall(CONTOUR_FT),
group = "Contours Lines", weight = 1) %>%
addLegend("bottomleft", pal = pall,
values = ~elevInter$CONTOUR_FT,
title = "Macleish Contour Line in feet") %>%
addPolylines(data = macleish_layers[["trails"]], weight = 2, label = ~name, color = ~palTrail(level), group = "Trails") %>%
addLegend("bottomright", pal = palTrail,
values = ~macleish_layers[["trails"]]$level,
title = "Difficulty levels for biking") %>%
addMeasure() %>%
addControl("Macleish Trails Ranked by Difficulty Levels", position = "topleft") %>%
addMiniMap(
toggleDisplay = TRUE) %>%
addProviderTiles(providers$OpenStreetMap) %>%
addProviderTiles("Esri.WorldTopoMap", group = "Topo") %>%
#and a satellite imagery map layer
addProviderTiles("Esri.WorldImagery", group = "Sat") %>%
#add the control to switch between the two
addLayersControl(baseGroups = c("OpenSreetMap", "Topo","Sat"),
options = layersControlOptions(collapsed = F)) %>%
addEasyButton(easyButton(
icon="fa-crosshairs", title="Locate Me",
onClick=JS("function(btn, map){ map.locate({setView: true}); }")))
#set color palette for contour lines
pall2 <- colorNumeric(palette="viridis",
domain= macleish_layers[["contours_3m"]]$ELEV_M)
#set color palette for different types of trails
palTrail <- colorFactor(c("red", "blue", "black"), domain = macleish_layers[["trails"]]$level)
#plot the graph with trails and contours line with leaflet
leaflet(data=macleish_layers[["trails"]]) %>%
addTiles() %>%
addPolylines(data=macleish_layers[["contours_3m"]],
color = ~pall2(ELEV_M),
group = "Contours Lines", weight = 1) %>%
addLegend("bottomleft", pal = pall2,
values = ~macleish_layers[["contours_3m"]]$ELEV_M,
title = "Macleish Contour Line in meters") %>%
addPolylines(data = macleish_layers[["trails"]], weight = 2, label = ~name, color = ~palTrail(level), group = "Trails") %>%
addLegend("bottomright", pal = palTrail,
values = ~macleish_layers[["trails"]]$level,
title = "Difficulty levels for biking") %>%
addMeasure() %>%
addControl("Macleish Trails Ranked by Difficulty Levels", position = "topleft") %>%
addMiniMap(
toggleDisplay = TRUE) %>%
addProviderTiles(providers$OpenStreetMap) %>%
addProviderTiles("Esri.WorldTopoMap", group = "Topo") %>%
#a satellite imagery map layer
addProviderTiles("Esri.WorldImagery", group = "Sat") %>%
#add the control to switch between the two
addLayersControl(baseGroups = c("OpenSreetMap", "Topo","Sat"),
options = layersControlOptions(collapsed = F)) %>%
addEasyButton(easyButton(
icon="fa-crosshairs", title="Locate Me",
onClick=JS("function(btn, map){ map.locate({setView: true}); }")))
To visualize the trails regrading their difficulty on a interactive map, we changed the color of easy trails to red, the color of moderate trails to black, and the color of hard trails to blue. We added labels instead of popups to each trail so that other people viewing our maps can see the name of the trail by simply moving the mouse onto the trail and the pop-up markers don’t block the other trails. We also changed the color of contour lines to visualize the change in elevation: the lowest would be in yellow and the highest would be in purple. We made two maps using data from contours250k and macleish layer contours_3m. In the map, the mini map can be minimized, and a locate_me button to show the position of the current viewer so that the viewer can see the distance between his or her current location and the macleish center.
We believe that Smith can use our classification in forming orientation group. Ride is one of the most popular outdoor orientation groups. Participants bike following the Norwottuck and Manhan Rail Trails and explore Mount Tom State Reservation. However, people with different background may feel the routes differently. For me, I don’t have much experience riding bicycles and I was really exhausted during that two days. But some people may feel pretty easy, and they have to stop to wait for other people. So I would suggest that Smith offers two orientation group for Ride, Ride I and Ride II. Ride I is for people don’t exercise much and don’t have much experience biking, while Ride II is for experienced bikers who are confident with riding uphills. Ride I can choose a trail in the moderate level, and Ride II can choose a trail in hard level. So people can choose the group that fits them well and it’s also a good opportunity for Smith to introduce Macleish field station to new-comers.
The distance between Smith College and Macleish field station is roughly 17.4 km, while the average length of the trails in difficult level is 2km. Since the average bike speed is 15.5 km/h, even though speed may vary according to the condition of the trail, we can assume that it takes no more than 2.5 hours for one way, which is a preferable time for a one-day bike trip. The implementation of the bike trail would also reduce the carbon footprint of the students since they are biking instead of taking the bus or driving, so it would have a positive influence on the environment. However, it is not possible for everyone to bike non-stop for 2 hours, so I encourage Smith to install water fountain and little gazebos alone the way so that the bikers can take the rest they need and continue the journey energetically.
Github link: https://github.com/ChristinaLyu/miniProject3.git↩